package vg.modules.backlight.components;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

import javax.swing.*;

import vg.services.data_base_manager.data.graph.Attribute;
import vg.services.data_base_manager.data.graph.Edge;
import vg.services.data_base_manager.data.graph.Graph;
import vg.services.data_base_manager.data.graph.Vertex;
import vg.services.graph_view_manager.interfaces.graph_view.AGraphView;
import vg.services.graph_view_manager.interfaces.graph_view.IGraphRenderer;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.actions.DefaultActionAdapter;

/**
 * This plugin finds critical paths in current subgraph.
 *
 * @author Timur Zolotuhin (e-mail: tzolotuhin@gmail.com)
 */
public class CriticalPathSearcher {
	private JButton button;
	private AGraphView view;
	private JDialog dialog;
	private JComboBox attributeComboBox = new JComboBox();
	private JComboBox directionComboBox = new JComboBox();
	private JCheckBox maxMinCheck = new JCheckBox();
	private Vertex from = null;
	private Vertex to = null;

	public CriticalPathSearcher() {
		button = new JButton(new ImageIcon("./data/resources/textures/critical.png"));
		button.setToolTipText("Find critical path beetwen two vertices");
		dialog = new JDialog((JFrame) null, "Critical path", true);

		JPanel contentPane = new JPanel(new GridBagLayout());
		dialog.setContentPane(contentPane);

        JButton okButton = new JButton("ok");
		JButton cancelButton = new JButton("cancel");

		contentPane.add(new JLabel("Attribute"), new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 10, 5, 5), 0, 0));
		contentPane.add(attributeComboBox, new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets(5, 10, 5, 5), 100, 0));
		contentPane.add(new JLabel("Maximum"), new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 10, 5, 5), 0, 0));
		contentPane.add(maxMinCheck, new GridBagConstraints(1, 1, 1, 1, 1, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 10, 5, 5), 0, 0));
		contentPane.add(new JLabel("Direction"), new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 10, 5, 5), 0, 0));
		contentPane.add(directionComboBox, new GridBagConstraints(1, 2, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 10, 5, 5), 0, 0));

		JPanel okCancelPane = new JPanel();
		okCancelPane.setLayout(new GridBagLayout());
		okCancelPane.add(okButton, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 10, 5, 5), 0, 0));
		okCancelPane.add(cancelButton, new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 10, 5, 5), 0, 0));
		contentPane.add(okCancelPane, new GridBagConstraints(0, 3, 2, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0,0));
		dialog.setResizable(false);
		dialog.pack();

        okButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				dialog.setVisible(false);
				final String attr = (String) attributeComboBox.getSelectedItem();
				view.addAction(new DefaultActionAdapter("show critical path action") {
                    @Override
                    public void action(final IGraphRenderer graphRenderer) {
                        if (directionComboBox.getSelectedIndex() == 0)
                            graphRenderer.showCriticalPath(from, to, maxMinCheck.isSelected(), attr);
                        else
                            graphRenderer.showCriticalPath(to, from, maxMinCheck.isSelected(), attr);
                    }
                });
			}
		});

        cancelButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				dialog.setVisible(false);
			}
		});

		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
                view.addAction(new DefaultActionAdapter("show critical path action") {
                    @Override
                    public void action(final IGraphRenderer graphRenderer) {
                        Graph ssg = graphRenderer.getOriginalSelectedSubGraph();
                        if (ssg != null) {
                            Collection<Vertex> lsv = ssg.getVertices();
                            if (lsv != null && lsv.size() == 2) {
                                Iterator<Vertex> it = lsv.iterator();
                                from = it.next();
                                to = it.next();

                                Object[] possibilities = { "from " + from.getStorableId() + " to " + to.getStorableId(),
                                        "from " + to.getStorableId() + " to " + from.getStorableId() };
                                directionComboBox.removeAllItems();
                                directionComboBox.addItem(possibilities[0]);
                                directionComboBox.addItem(possibilities[1]);
                                attributeComboBox.removeAllItems();
                                HashSet<String> attrset = new HashSet<String>();
                                for (Edge edge : graphRenderer.getOriginGraph().getEdges()) {
                                    for (Attribute attr : edge.getAttributes()) {
                                        if (attr.isRealType())
                                            attrset.add(attr.getName());
                                    }
                                }
                                for (String attr : attrset) {
                                    attributeComboBox.addItem(attr);
                                }
                                dialog.setVisible(true);
                            }
                        }
                    }
                });
			}
		});
		button.setEnabled(false);
	}

	public JComponent getView() {
		return button;
	}

	public void setEnabled(boolean enable) {
		button.setEnabled(enable);
    }

	public void changeView(AGraphView igv) {
		this.view = igv;
		if (view == null) {
			setEnabled(false);
		}
	}
}
